/*
 * @Author: Wangjun
 * @Date: 2023-05-19 16:51:32
 * @LastEditTime: 2023-10-29 21:19:04
 * @LastEditors: Wangjun
 * @Description:
 * @FilePath: \ai_tradee:\go\src\gitee.com\haodreams\golib\js\jsutil\jsthis.go
 * hnxr
 */
package jsutil

import (
	"bytes"
	"encoding/json"
	"net/url"
	"time"

	"gitee.com/haodreams/golib/easyurl"
	"gitee.com/haodreams/golib/logs"
	"gitee.com/haodreams/golib/lz4file"
	"gitee.com/haodreams/libs/easy"
	"gitee.com/haodreams/libs/expr"
	"gitee.com/haodreams/libs/safe"
	"github.com/dop251/goja"
	"github.com/ugorji/go/codec"
	"golang.org/x/text/encoding/simplifiedchinese"
)

var (
	//缓存是全局通用的
	cacheString = safe.NewSafeMap[string, string]()
	cacheNumber = safe.NewSafeMap[string, float64]()
)

type Setuper interface {
	Setup(vm *goja.Runtime)
}

type JsThis struct {
	buf bytes.Buffer
	// cacheString *safe.SafeMap[string, string]
	// cacheNumber *safe.SafeMap[string, float64]
}

type JsCtx struct {
	JsThis
	vm *goja.Runtime
}

/**
 * @description: 获取vm
 * @return {*}
 */
func (m *JsCtx) VM() *goja.Runtime {
	return m.vm
}

func (m *JsCtx) Now() time.Time {
	return time.Now()
}

func (m *JsCtx) Clock() string {
	return time.Now().Format("150405")
}

func (m *JsCtx) UsedTime(now time.Time) string {
	return time.Since(now).String()
}

// Interrupt 强制停止
func (m *JsCtx) Interrupt(obj any) {
	m.vm.Interrupt(obj)
}

func New(s Setuper, vm *goja.Runtime) Setuper {
	s.Setup(vm)
	InitModels(vm)
	return s
}

func (m *JsCtx) Setup(vm *goja.Runtime) {
	m.vm = vm
}

/**
 * @description: 获取linux 时间戳
 * @return {*}
 */
func (m *JsCtx) Unix() int64 {
	return time.Now().Unix()
}

/**
 * @description: 获取linux 时间戳
 * @return {*}
 */
func (m *JsCtx) UnixMilli() int64 {
	return time.Now().UnixMilli()
}

/**
 * @description: 格式化时间
 * @param {int64} unix unix 时间戳
 * @param {string} fmt
 * @return {*}
 */
func (m *JsCtx) FormatTime(unix int64, fmt string) string {
	if fmt == "" {
		return easy.FormatTime(unix, easy.YYYYMMDDHHMMSS)
	}
	return easy.FormatTime(unix, easy.ConvertFormat(fmt))
}

/**
 * @description: 格式化时间
 * @param {int64} unix unix 时间戳
 * @param {string} fmt
 * @return {*}
 */
func (m *JsCtx) FormatNow(fmt string) string {
	if fmt == "" {
		return time.Now().Format(easy.YYYYMMDDHHMMSS) //easy.FormatTime(unix, easy.YYYYMMDDHHMMSS)
	}
	return time.Now().Format(easy.ConvertFormat(fmt))
}

// 常用函数
func (m *JsThis) Max(x ...float64) float64 {
	v, _ := expr.Max(x...)
	return v
}

func (m *JsThis) Min(x ...float64) float64 {
	v, _ := expr.Min(x...)
	return v
}

func (m *JsThis) Avg(x ...float64) float64 {
	v, _ := expr.Avg(x...)
	return v
}

func (m *JsThis) Sum(x ...float64) float64 {
	v, _ := expr.Sum(x...)
	return v
}

func (m *JsThis) IF(x ...float64) float64 {
	v, _ := expr.IF(x...)
	return v
}

/**
 * @description: 设置缓存的字符串
 * @param {string} key
 * @param {string} value
 * @return {*}
 */
func (m *JsThis) SetString(key string, value string) {
	cacheString.Set(key, &value)
}

/**
 * @description: 获取缓存的字符串
 * @param {string} key
 * @return {*}
 */
func (m *JsThis) GetString(key string) string {
	value, _ := cacheString.Get(key)
	if value == nil {
		return ""
	}
	return *value
}

/**
 * @description: 缓存设置数字数据
 * @param {string} key
 * @param {float64} value
 * @return {*}
 */
func (m *JsThis) SetNumber(key string, value float64) {
	cacheNumber.Set(key, &value)
}

/**
 * @description: 获取缓存的字符串
 * @param {string} key
 * @return {*}
 */
func (m *JsThis) GetNumber(key string) float64 {
	value, _ := cacheNumber.Get(key)
	if value == nil {
		return 0
	}
	return *value
}

/**
 * @description: 保存缓存
 * @param {string} path
 * @return {*}
 */
func SaveString(path string) (err error) {
	mh := new(codec.MsgpackHandle)
	buf := bytes.NewBuffer(nil)
	err = codec.NewEncoder(buf, mh).Encode(cacheString.GetKVs())
	if err != nil {
		logs.Warn(err)
		return
	}

	err = lz4file.SaveLz4File(path, buf.Bytes())
	return
}

/**
 * @description: 加载文件到缓存
 * @param {string} path
 * @return {*}
 */
func LoadString(path string) (err error) {
	data, err := lz4file.LoadLz4File(path)
	if err != nil {
		return
	}
	mh := new(codec.MsgpackHandle)
	var kvs []*safe.KV[string, string]
	err = codec.NewDecoder(bytes.NewBuffer(data), mh).Decode(&kvs)
	cacheString.SetKVs(kvs)
	return
}

/**
 * @description: 保存缓存
 * @param {string} path
 * @return {*}
 */
func SaveNumber(path string) (err error) {
	mh := new(codec.MsgpackHandle)
	buf := bytes.NewBuffer(nil)
	err = codec.NewEncoder(buf, mh).Encode(cacheNumber.GetKVs())
	if err != nil {
		logs.Warn(err)
		return
	}

	err = lz4file.SaveLz4File(path, buf.Bytes())
	return
}

/**
 * @description: 加载文件到缓存
 * @param {string} path
 * @return {*}
 */
func LoadNumber(path string) (err error) {
	data, err := lz4file.LoadLz4File(path)
	if err != nil {
		return
	}
	mh := new(codec.MsgpackHandle)
	var kvs []*safe.KV[string, float64]
	err = codec.NewDecoder(bytes.NewBuffer(data), mh).Decode(&kvs)
	cacheNumber.SetKVs(kvs)

	return
}

/**
 * @description: get 请求
 * @param {string} url
 * @return {*}
 */
func (m *JsThis) Get(url string) any {
	data, _, err := easyurl.Get(url, nil)
	if err != nil {
		return err
	}
	return string(data)
}

/**
 * @description: pos 请求
 * @param {string} url
 * @return {*} 返回的数据是json
 */
func (m *JsThis) GET(url string) string {
	data, code, err := easyurl.Get(url, nil)
	if err != nil {
		return `{"code":0,"error":null}`
	}
	kv := map[string]any{"data": string(data), "code": code, "error": nil}
	data, _ = json.Marshal(kv)
	return string(data)
}

/**
 * @description: pos 请求
 * @param {string} url
 * @return {*}返回的数据是json
 */
func (m *JsThis) POST(url string) string {
	data, code, err := easyurl.Post(url, nil)
	if err != nil {
		return `{"code":0,"error":null}`
	}
	kv := map[string]any{"data": string(data), "code": code, "error": nil}
	data, _ = json.Marshal(kv)
	return string(data)
}

/**
 * @name: 参数转义
 * @msg:
 * @param {string} p
 * @return {*}
 */
func (m *JsThis) Escape(p string) string {
	return url.QueryEscape(p)
}

/**
 * @description: get 请求
 * @param {string} url
 * @return {*}返回的数据是json
 */
func (m *JsThis) GetJSON(url string) string {
	data, code, err := easyurl.Get(url, nil)
	if err != nil {
		return `{"code":0,"error":null}`
	}
	kv := map[string]any{"data": string(data), "code": code, "error": nil}
	data, _ = json.Marshal(kv)
	return string(data)
}

/**
 * @description: 休眠毫秒
 * @param {int} ms
 * @return {*}
 */
func (m *JsThis) Sleep(ms int) {
	if ms <= 0 {
		return
	}
	time.Sleep(time.Millisecond * time.Duration(ms))
}

/**
 * @description: pos json请求
 * @param {string} url
 * @return {*}返回的数据是json
 */
func (m *JsThis) PostJSON(url string, jsdata string) any {
	data, code, err := easyurl.JSON(url, jsdata)
	if err != nil {
		return `{"code":-1,"error":null}`
	}
	kv := map[string]any{"data": string(data), "code": code, "error": nil}
	data, _ = json.Marshal(kv)
	return string(data)
}

/**
 * @description: gbk 转为utf8编码
 * @param {string} data
 * @return {*}
 */
func (m *JsThis) UTF8(data string) string {
	ret, _ := simplifiedchinese.GBK.NewDecoder().String(data)
	return ret
}

/**
 * @description: gbk 转为utf8编码
 * @param {string} data
 * @return {*}
 */
func (m *JsThis) GBK(data string) string {
	ret, _ := simplifiedchinese.GBK.NewEncoder().String(data)
	return ret
}

/**
 * @description: 清空buf的数据
 * @return {*}
 */
func (m *JsThis) BufReset() {
	m.buf.Reset()
}

/**
 * @description: 写入数据到buf
 * @param {string} data
 * @return {*}
 */
func (m *JsThis) BufPush(data string) {
	m.buf.WriteString(data)
}

/**
 * @description: 写入数据到buf
 * @param {string} data
 * @return {*}
 */
func (m *JsThis) BufWrite(data string) {
	m.buf.WriteString(data)
}

/**
 * @description: 获取buf的字符串
 * @return {*}
 */
func (m *JsThis) BufString() string {
	return m.buf.String()
}
